package com.yao.mymvc.servlet;

import com.yao.myioc.factory.support.DefaultListableBeanFactory;
import com.yao.myioc.reader.XmlBeanDefinitionReader;
import com.yao.myioc.resource.ClasspathResource;
import com.yao.myioc.resource.Resource;
import com.yao.mymvc.handleradapter.ModelAndView;
import com.yao.mymvc.handleradapter.iface.HandlerAdapter;
import com.yao.mymvc.handlermapping.iface.HandlerMapping;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

/**
 * @author Henry Yao
 */
public class DispatchServlet extends AbstractHttpServlet {
    /**
     * beanfactory 获取bean
     */
    private DefaultListableBeanFactory beanFactory;
    /**
     * 处理器映射器的策略集合
     */
    private List<HandlerMapping> handlerMappings;

    private List<HandlerAdapter> handlerAdapters;

    @Override
    protected void doDispatch(HttpServletRequest req, HttpServletResponse resp) {
        try { // 1、获取请求url对应的handler
            Object handler = getHandler(req);
            // 2、找到对应handler对应的handlerAdapter
            if (handler == null) {
                System.out.println("未找到对应的handler");
                return;
            }
            HandlerAdapter adapter = getAdapter(handler);
            // 3、执行handlerAdapter的方法返回结果
            if (adapter == null) {
                System.out.println("未找到对应处理器适配器");
                return;
            }
            ModelAndView modelAndView = adapter.handleRequest(handler, req, resp);
            // 4、对返回结果进行处理
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private HandlerAdapter getAdapter(Object handler) {
        HandlerAdapter adapter = null;
        // 遍历所有的adapter查找器，查看是否与当前handler匹配
        if (handlerAdapters != null && handlerAdapters.size() > 0) {
            for (HandlerAdapter ha : handlerAdapters) {
                try {
                    if (ha.supports(handler)) {
                        return ha;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }


    /**
     * 获取请求对应的handler
     *
     * @param req
     */
    private Object getHandler(HttpServletRequest req) {
        Object handler = null;
        // 遍历所有的handler查找器，执行他们的查找方法，如果有一个有返回结果则返回该结果
        if (handlerMappings != null && handlerMappings.size() > 0) {
            for (HandlerMapping hm : handlerMappings) {
                try {
                    handler = hm.getHandler(req);
                    if (handler != null) {
                        return handler;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    /**
     * servlet 初始化时会执行该方法
     *
     * @param config
     * @throws ServletException
     */
    @Override
    public void init(ServletConfig config) throws ServletException {
        // 从web.xml中读取spring的配置文件地址
        String location = config.getInitParameter("contextConfigLocation");
        // 初始化spring容器
        initSpringContainer(location);
        // 初始化策略集合
        initHandlerMappings();
        initHandlerAdapters();

    }

    private void initHandlerMappings() {
        // 从spring容器中，初始化所有的HandlerMapping的策略
        handlerMappings = beanFactory.getBeansByType(HandlerMapping.class);
    }

    private void initHandlerAdapters() {
        handlerAdapters = beanFactory.getBeansByType(HandlerAdapter.class);
    }

    private void initSpringContainer(String location) {
        beanFactory = new DefaultListableBeanFactory();
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
        Resource resource = new ClasspathResource(location);
        reader.loadBeanDefinitions(resource);
    }
}
